using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;



using SharedLibrary; //My library
//Ink step 1: Add using for ink with the reference .. in my case the Assembly is OpenNETCF.WindowsMobile.Ink stored in C:\Program Files\OpenNETCF\Shared Source\Mobile Ink Library\Bin\OpenNETCF.WindowsMobile.Ink.dll
using OpenNETCF.WindowsMobile.Ink;
using OpenNETCF.WindowsMobile.Ink.Interfaces;

////Client connection step 1: Add using 
using System.Net;
using System.Net.Sockets;
using System.IO;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Threading;

namespace MobileTouchPad
{
    public partial class FormTouchPad : Form
    {

        //Ink step 2: add the overlay
        IInkOverlay m_overlay;

        //Client connection step 2: add the variable
        TcpClient m_tcpclient;
        NetworkStream m_networkstream;

        //Store the last movements 
        Point LastPoint;
        int licznik = 0;
        Size currSize;
        Object semaphore = new Object() ;

        SharedLibrary.CommonStruct.WorkMode mode = SharedLibrary.CommonStruct.WorkMode.TouchPad;
        
        CommonStruct.MouseButtonState m_buttonState= CommonStruct.MouseButtonState.None;
        Thread PCdesktopRefresher;

        public FormTouchPad()
        {
            InitializeComponent();
         
            ResetLastPoint();
            PCdesktop.Visible = false;
            currSize = this.Size;
        }
        
        private void ResetLastPoint()
        {
            LastPoint.X = -1;
            LastPoint.Y = -1;
        }

        private void InitializeInk()
        {
            //Ink step 3: Add the event stroke
            m_overlay = Ink.CreateInstance();
            m_overlay.SetEventInterest(InkCollectorEventInterest.Stroke, true);

            //Ink step 4: Attach the panel to the overlay
            m_overlay.hWnd = panelTouchPad.Handle;
            m_overlay.Enabled = true;
            this.Text = "";
        }

        private void InitializeTcpConnection()
        {
            //Client connection step 3: Initialize the client
            m_tcpclient = new TcpClient();
        }

        //Ink step 5: Clrscr
        private void ClearTouchPad()
        {
            //clear the screen if not in use
            try
            {

                m_overlay.Enabled = false;
                m_overlay.Ink = InkDisp.CreateInstance();
                m_overlay.Enabled = true;

                ResetLastPoint();
            }
            catch
            {
            }
        }


        private void TouchPad_Load(object sender, EventArgs e)
        {
            InitializeInk();
            InitializeTcpConnection();
            ConnectToDesktop();

        }

        private void TouchPad_Resize(object sender, EventArgs e)
        {
            //retrive the screen coordinate
            Rectangle oScreen = Screen.PrimaryScreen.WorkingArea;

            //if (mode == CommonStruct.WorkMode.TouchPad)
            {
                //Adapt the pictureBox1 to the screen
                panelTouchPad.Location = new System.Drawing.Point(0, 0);
                panelTouchPad.Size = new System.Drawing.Size(oScreen.Size.Width, oScreen.Size.Height - oScreen.Y);
            }
            //else if (mode == CommonStruct.WorkMode.TouchScreen)
            {
                PCdesktop.Location = new Point(0, 0);
                PCdesktop.Size = new System.Drawing.Size(oScreen.Size.Width, oScreen.Size.Height - oScreen.Y); ;
            }
            currSize = PCdesktop.Size;
        }

     

        private bool ConnectToDesktop()
        {
            if (!IsActiveSyncConnected())
            {
                MessageBox.Show("ActiveSync connection not available, Continue without desktop interaction.","Error");
            }
            else
            {
                //the activeSync connection is available 
                try
                {                  
                    Console.WriteLine("Connecting.....");
                    //Client connection step 4: Connect to the server
                    m_tcpclient.Connect("PPP_PEER", 5000);

                    m_networkstream = m_tcpclient.GetStream();
                    
                    Console.WriteLine("Connected");

                    return true;

                   
                }

                catch (Exception e)
                {
                    string sErroMsg = e.Message;
                    MessageBox.Show("Error connection with desktop. No desktop interaction.\n" + sErroMsg , "Error");
                }
            }
            return false;
        }


        public bool IsActiveSyncConnected()
        {
            try
            {
                // Check if the connection with activeSync is available reading the desktop Ip
                // [HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\ppp_peer]
                RegistryKey pRegKey = Registry.LocalMachine.OpenSubKey(@"Comm\Tcpip\Hosts\ppp_peer", false);
                if (pRegKey == null)
                {
                    //if not exist try [HKEY_LOCAL_MACHINE\Comm\Tcpip\Hosts\dtpt_peer]
                    RegistryKey pRegKey2 = Registry.LocalMachine.OpenSubKey(@"Comm\Tcpip\Hosts\dtpt_peer", false);
                    if (pRegKey2 == null)
                    {
                        Console.WriteLine("Device is not ready. Verify whether ActiveSync connection is running.");
                        return false;
                    }
                    pRegKey = pRegKey2;
                }

                Object ServerIpAddress = pRegKey.GetValue("ipaddr");

                IPAddress ipServer = new IPAddress((byte[])ServerIpAddress);

                Console.WriteLine("Endpoint found at: " + ipServer.ToString());
                //"192.160.50.100"
                //"169.254.2.2"

            }
            catch
            {
            }

            try
            {
                

                //System.Net.Dns.Resolve("ppp_peer");
                System.Net.Dns.GetHostEntry("ppp_peer");
                
                Console.WriteLine("AcriveSync connected.");
                return true;
            }
            catch (System.Net.Sockets.SocketException socketException)
            {
                Console.WriteLine("AcriveSync si no connected. ");
                Console.WriteLine("Socket Error: " + socketException.Message);

            }
            return false;
        }


        private void panelTouchPad_MouseMove(object sender, MouseEventArgs e)
        {
            if (mode == CommonStruct.WorkMode.TouchPad)
            {
                if ((LastPoint.X == -1) && (LastPoint.Y == -1))
                {
                    LastPoint.X = e.X;
                    LastPoint.Y = e.Y;
                    //The start point is not sent to the server
                    return;
                }
                else
                {
                    Point pointDirection = new Point();
                    pointDirection.X = e.X - LastPoint.X;
                    pointDirection.Y = e.Y - LastPoint.Y;

                    CommunicateCritical(pointDirection, CommonStruct.WorkMode.TouchPad);

                    LastPoint.X = e.X;
                    LastPoint.Y = e.Y;
                }
            }
            else if (mode == CommonStruct.WorkMode.TouchScreen)
            {
                CommunicateCritical(new Point(e.X, e.Y), mode);
            }
        }

        private void SendData(Point pointDirection, CommonStruct.WorkMode mode)
        {
            ++licznik;
            try
            {
                this.Text = "m: " + licznik;
            }
            catch(NotSupportedException e) 
            {
            }
            try
            {
                //Client connection step 5: a check for the connection
                if (m_networkstream != null)
                {
                    CommonStruct.TouchPro AddMove = new CommonStruct.TouchPro();

                    AddMove.point = pointDirection;
                    AddMove.buttonState = m_buttonState;
                    AddMove.mode = mode;
                    AddMove.currSize = currSize;
                    AddMove.Sequence = licznik;
                    //AddMove.buttonDblClick = m_buttonDblClick;

                    object objTmp = (object)AddMove;
                    Byte[] data = CommonConvertion.StructureToByteArray(AddMove);

                    //Client connection step 6: Send the data to server
                    m_networkstream.Write(data, 0, data.Length);
                }

                
            }
            catch (IOException IOEx)
            {
                Console.WriteLine("Lost the connection? " );
                Console.WriteLine("SendData Error: IOException: " + IOEx.Message);
            }
            catch (ArgumentNullException ArgumentEx)
            {
                Console.WriteLine("SendData Error: ArgumentNullException: " + ArgumentEx.Message);
            }
            catch (SocketException sochetEx)
            {
                Console.WriteLine("SendData Error: SocketException: " + sochetEx.Message);
            }
        }

        public void ReciveDesktop()
        {
            try
            {
                BinaryReader br = new BinaryReader(m_networkstream) ;
                MemoryStream ms = new MemoryStream((int)br.ReadInt64());
                int seq = br.ReadInt32();
                if (seq != licznik)
                    MessageBox.Show("Trouble with sync sequence! We have " + seq + " should be " + licznik, "Attention!");
                byte[] buff = new byte[255];
                int size = 0;
                while (size < ms.Capacity)
                {
                    int s = m_networkstream.Read(buff, 0, 255);
                    ms.Write(buff, 0, s);
                    size += s;
                }
                Bitmap PCscreen = new Bitmap(ms);
                PCdesktop.Size = PCscreen.Size;
                PCdesktop.Image = PCscreen;
            }
            catch (Exception e)
            {
                Console.WriteLine("SendData Error: SocketException: " + e.Message);
            }
        }
       
        private void TouchPad_Closing(object sender, CancelEventArgs e)
        {
            //Client connection step 7: Close the connection
            try
            {
                if (m_tcpclient != null)
                    m_tcpclient.Close();
                if (m_networkstream != null)
                    m_networkstream.Close();
            }
            catch
            {
            }
        }
                       
        //remember to enable the timer
        private void timerClearScreen_Tick(object sender, EventArgs e)
        {
            ClearTouchPad();
        }

        private void panelTouchPad_DoubleClick(object sender, EventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.DblClick;
            CommunicateCritical(new Point(0, 0), mode);
        }

        private void FormTouchPad_KeyDown(object sender, KeyEventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.ButtonPressed;
            CommunicateCritical(new Point(0, 0), mode);
        }

        private void FormTouchPad_KeyUp(object sender, KeyEventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.None;
            CommunicateCritical(new Point(0, 0), mode);
        }

        private void panelTouchPad_Click(object sender, EventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.ButtonClick;
            CommunicateCritical(new Point(0, 0), mode);
        }

        private void ModeMenu_Click(object sender, EventArgs e)
        {
            if (mode == CommonStruct.WorkMode.TouchPad)
            {
                mode = CommonStruct.WorkMode.TouchScreen;
                panelTouchPad.Visible = false;
                panelTouchPad.Enabled = false;
                PCdesktop.Visible = true;
                PCdesktop.Enabled = true;
                m_buttonState = CommonStruct.MouseButtonState.None;
                PCdesktopRefresher = new Thread(PCdesktopUpdate);
                PCdesktopRefresher.Start();
            }
            else if (mode == SharedLibrary.CommonStruct.WorkMode.TouchScreen)
            {
                mode = SharedLibrary.CommonStruct.WorkMode.TouchPad;
                panelTouchPad.Visible = true;
                panelTouchPad.Enabled = true;
                PCdesktop.Visible = false;
                PCdesktop.Enabled = false;
                m_buttonState = CommonStruct.MouseButtonState.None;
                CommunicateCritical(new Point(0, 0), mode);
            }
        }

        private void PCdesktopMouseDown(object sender, MouseEventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.ButtonPressed;
            CommunicateCritical(new Point(e.X, e.Y), mode);
        }

        private void PCdesktopMouseUp(object sender, MouseEventArgs e)
        {
            m_buttonState = CommonStruct.MouseButtonState.None;
            CommunicateCritical(new Point(e.X, e.Y), mode);
        }
        private void PCdesktopUpdate()
        {
            Point p = new Point(-1, -1);
            while (mode == CommonStruct.WorkMode.TouchScreen)
            {
                CommunicateCritical(p, mode);
                Thread.Sleep(1000);
            }
        }
        private void CommunicateCritical(Point p, SharedLibrary.CommonStruct.WorkMode mode)
        {
            lock (semaphore)
            {
                semaphore = true;
                SendData(p, mode);
                if (mode == CommonStruct.WorkMode.TouchScreen)
                    ReciveDesktop();
            }
        }
    }
}